
using System;
using System.Collections;
using System.Collections.Generic;
using System.Xml;
using Gtk;

namespace Designer
{
	public partial class ResourceMgr : SingletonManager<ResourceMgr>
	{        
		const string VERSION = "0.1.1"; //must have 3 parts with 1 digit each
		public string tempDir;
		public ArrayList actionSets = new ArrayList();
		public TreeView tree;
		public TreeStore store;
		public MainWindow Win;
		public Hashtable GameSettings = new Hashtable();

		public ActionSet GetActionSetByName(string n)
		{
			foreach(ActionSet aset in actionSets)
			{
				if(aset.name == n)
				return aset;
			}
			return null;
		}
		public void Init(TreeView tree, MainWindow win)
		{
			this.Win = win;
			this.tree = tree;
			store = (TreeStore) tree.Model;
			ActionSet std = new ActionSet("Standard");
			std.AddAction("Code");
			actionSets.Add(std);
			actionSets.Add(new ActionSet("Ext 1"));
			GameSettings["StartFullScreen"] = false;
			GameSettings["AllowCloseButton"] = true;
			GameSettings["AllowESC"] = true;
			GameSettings["AllowF4"] = true;
		}
		
		Dictionary<TreeIter,Resource> list = new Dictionary<TreeIter,Resource>();
		public List<Resource> ResourceList
		{
			get
			{
				List<Resource> l = new List<Resource>();
				foreach(Resource r in list.Values)
					l.Add(r);
				return l;
			}
		}
		public Hashtable nameList = new Hashtable();
		public Resource GetResourceByPath(TreePath path)
		{
			TreeIter iter;
			store.GetIter(out iter, path);
			return GetResourceByIter(iter);
		}
		public Resource GetResourceByIter(TreeIter iter)
		{
			string searchpath = store.GetPath(iter).ToString();
			foreach(KeyValuePair<TreeIter,Resource> entry in ResourceMgr.Instance.list)
			{
				if(store.GetPath(entry.Key).ToString() == searchpath)
				{
					return entry.Value;
				}
			}
			TreePath path = new TreePath(searchpath);
			if(path.Depth >= 3)
			{
				TreePath childPath = new TreePath(path.ToString());
				path.Up();
				Resource res = GetResourceByPath(path);
				if(res is Obj)
				{
					Obj o = res as Obj;
					Event e = o.events[childPath.Indices[childPath.Depth-1]];
					return e;
				}
				
			}
			throw new ArgumentException("Iter doesn't exist");
		}
		public bool ResourceNameExists(string name)
		{
			foreach(Resource res in list.Values)
			{
				if(name == res.Name) return true;
			}
			return false;
		}
		public bool ResourceExists(Resource res)
		{
			return list.ContainsValue(res);
		}
		public Resource GetResourceByName(string type, string name)
		{
			foreach(Resource res in list.Values)
			{
				if(res.GetResType() == type && res.Name == name)
				{
					return res;
				}
			}
			throw new ArgumentException("Resource with type "+type+" and name "+name+" doesn't exist");
		}
		public TreeIter GetIterByResource(Resource res)
		{
			foreach(KeyValuePair<TreeIter,Resource> entry in ResourceMgr.Instance.list)
			{
				if(entry.Value == res)
				{
					return entry.Key;
				}
			}
			throw new ArgumentException("Resource doesn't exist");
		}
		public void AddResource(string type)
		{
			List<string> names = new List<string>();
			foreach(Resource res in list.Values)
				names.Add(res.Name);
			string resName;
			int i = 0;
			do
			{
				i++;
				resName = "neu"+i;
			}
			while(names.Contains(resName));
			// Resource newRes = null; 
			TreeIter addIter = store.AppendValues (Win.ResGroups[type], resName);
			Resource newRes = Create(type, resName);
			tree.ExpandRow(store.GetPath(Win.ResGroups[type]),false);
			Console.WriteLine("Added "+type+" "+resName);
			list.Add(addIter,newRes);
			foreach(KeyValuePair<Resource,iEditTab> entry in Win.editTabsList)
			{
				iEditTab tabEntry = (iEditTab) entry.Value;
				tabEntry.Reload(); //reload on add resource
			}
			Win.unsavedChanges = true;
		}
		public void DeleteResource(Resource res)
		{
			TreeIter iter = GetIterByResource(res);
			if(res is Obj)
			{
				Console.WriteLine("Deleting "+res.Name+" and all of it's instances");
				foreach(Resource r in list.Values)
				{
					if(r is Room)
						(r as Room).DeleteInstancesOfObj(res as Obj);
					foreach(KeyValuePair<Resource,iEditTab> entry in Win.editTabsList)
					{
						if(entry.Value is RoomEditTab)
						{
							(entry.Value as RoomEditTab).DeleteInstanceOfObj(res as Obj);
						}
					}
				}
			}
			else
				Console.WriteLine("Deleting "+res.Name);
			Win.CloseEditTab(res, false);
			list.Remove(iter);
			store.Remove(ref iter);
			Win.ReloadEditTabs();
			Win.unsavedChanges = true;
		}
		public void ChangeResourceName(Resource res, string newName)
		{
			if(res.Name == newName || res is Event) return;
			TreeIter iter = GetIterByResource(res);
			Console.WriteLine("Changing name of "+res.Name+" to "+newName);
			res.SetName(newName);
			store.SetValue(iter,0,newName);
		}
		
		Resource Create(string type, string name)
		{
			switch(type)
			{
				case "Sprite":
					return new Gra(name);
				case "Background":
					return new Back(name);
				case "Object":
					return new Obj(name);
				case "Room":
					return new Room(name);
				case "Class":
					return new Cla(name);
				case "Font":
					return new Font(name);
				default:
					return new Resource();
			}
		}
		public object ReadXmlValue(XmlNode child, bool ResToList)
		{
			if(child.Name == "Color")
			{
				byte cr, cg, cb;
				cr = byte.Parse(child.Attributes["r"].InnerText);
				cg = byte.Parse(child.Attributes["g"].InnerText);
				cb = byte.Parse(child.Attributes["b"].InnerText);
				return new Gdk.Color(cr, cg, cb);
			}
			if(child.Name == "Resource")
			{
				if(ResToList)
				{
					ArrayList arrlist = new ArrayList();
					arrlist.Add(child.Attributes["type"].InnerText);
					arrlist.Add(child.Attributes["name"].InnerText);
					//Füge der Ressourcen Liste einen Eintrag hinzu, um ihn nach dem Laden aller Ressourcen auszuwerten
					return arrlist;
				}
				else
				{
					return GetResourceByName(child.Attributes["type"].InnerText, child.Attributes["name"].InnerText);
				}
			}
			if(child.Name == "Bool")
			{
				return bool.Parse(child.Attributes["value"].InnerText);;
			}
			if(child.Name == "Int")
			{
				return int.Parse(child.Attributes["value"].InnerText);
			}
			if(child.Name == "String")
			{
				return child.Attributes["value"].InnerText;
			}
			if(child.Name == "File")
			{
				FileResource fr = new FileResource();
				fr.TempFile = child.Attributes["filename"].InnerText;
				return fr;
			}
			
			return null;
		}
		public bool WriteXmlValue(XmlTextWriter writer, object Value)
		{
			if(Value is Gdk.Color)
			{
				Gdk.Color col = (Gdk.Color) Value;
				//Errechne byte Werte aus den Farbwerten
				byte cr, cg, cb;
				cr = (byte) (col.Red * 255 / 65535);
				cg = (byte) (col.Green * 255 / 65535);
				cb = (byte) (col.Blue * 255 / 65535);
				//Schreibe Farbtag
				writer.WriteStartElement("Color");
				writer.WriteAttributeString("r", cr.ToString());
				writer.WriteAttributeString("g", cg.ToString());
				writer.WriteAttributeString("b", cb.ToString());
				writer.WriteEndElement();
			}
			//Wenn die Option ein Verweis auf eine Ressource ist, schreibe spezielles Ressourcentag
			else if(Value is Resource)
			{
				Resource myRes = (Resource) Value;
				writer.WriteStartElement("Resource");
				//Schreibe Typ und Name der Ressource, um später wieder einen Verweis zu ermitteln
				writer.WriteAttributeString("type", myRes.GetResType());
				writer.WriteAttributeString("name", myRes.Name);
				writer.WriteEndElement();
			}
			//Wenn die Option eine bool-Variable ist, schreibe spezielles bool-Tag
			else if(Value is Boolean)
			{
				bool val = (bool) Value;
				writer.WriteStartElement("Bool");
				writer.WriteAttributeString("value", val.ToString().ToLower());
				writer.WriteEndElement();
			}
			//Wenn die Option eine Ganzzahl ist, schreibe spezielles Int-Tag
			else if(Value is Int32)
			{
				int val = (int) Value;
				writer.WriteStartElement("Int");
				writer.WriteAttributeString("value", val.ToString());
				writer.WriteEndElement();
			}
			else if(Value is FileResource)
			{
				FileResource fr = (FileResource)Value;
				writer.WriteStartElement("File");
				writer.WriteAttributeString("filename",fr.TempFile);
				writer.WriteEndElement();
			}
			else if(Value is string)
			{
				string val = (string) Value;
				writer.WriteStartElement("String");
				writer.WriteAttributeString("value", val);
				writer.WriteEndElement();
			}
			else
				return false;
			
			return true;
		}
	}
}
